#pragma once

#include "InetAddr.hpp"
#include "Socket.hpp"
#include "TcpServer.hpp"
#include "Util.hpp"
#include "Log.hpp"
#include <cstdint>
#include <memory>
#include <mutex>
#include <sstream>
#include <string>
#include <unordered_map>

using namespace LogModule;
using namespace SocketModule;

const std::string gsp = " ";
const std::string glinespace = "\r\n";

const std::string webroot = "./wwwroot";
const std::string glinesep = ": "; // 默认分割符
const std::string homepage = "index.html"; // 默认首页
const std::string page_404 = "/404.html";
class HttpRequest { // 对http请求的处理
public:
    HttpRequest() {}
    std::string Serialize() {
        return std::string();
    }
    bool Deserialisze(std::string str) {
        std::string reqline; // 对请求行进行提取
        bool res = Util::ReadOneLine(str, &reqline, glinespace);
        LOG(LogLevel::DEBUG) << reqline;

        // 对请求行进程反序列化
        ParseReqLine(reqline);
        LOG(LogLevel::DEBUG) << "method: " << _method;
        LOG(LogLevel::DEBUG) << "uri: " << _uri;
        LOG(LogLevel::DEBUG) << "version: " << _version;
        if(_uri == "/") {
            _uri = webroot + _uri + homepage;
        }else {
            _uri = webroot + _uri;
        }
        return true;
    }
    void ParseReqLine(std::string& reqline) { // 这里是用来提取我们的请求行相关信息的
        // 使用stringstream自动识别并提取
        std::stringstream ss(reqline);
        ss >> _method >> _uri >> _version; // 请求方法 请求的uri 请求的版本号
    }
    std::string uri() {
        return _uri;
    }
    ~HttpRequest() {}
private:
    std::string _method;
    std::string _uri;
    std::string _version;
    std::unordered_map<std::string, std::string> _header;
    std::string _blankline;
    std::string _text;
};
class HttpResponse {
public:
    HttpResponse() : _blankline(glinespace) {
    }
    std::string Serialize() { // 序列化
        std::string status_line = _version + gsp + std::to_string(_code) + gsp + _desc + glinespace;
        std::string resp_header;
        for(auto& header : _headers) {
            std::string line = header.first + glinesep + header.second + glinespace;
            resp_header += line;
        }
        return status_line + resp_header + _blankline + _text;
    }
    void SetTargetFile(const std::string& tar) {
        _targetfile = tar;
    }
    bool MakeResponse() {
        bool res = Util::ReadFileContent(_targetfile, &_text);
        if(!res) {
            _code = 404;
            _desc = "Not Found";
        }
    }
    bool Deserialisze() {
        return true;
    }
public:
    std::string _version;
    int _code;
    std::string _desc;
    std::unordered_map<std::string, std::string> _headers;
    std::string _blankline;
    std::string _text;
    std::string _targetfile;
};
class Http {
public:
    Http(uint16_t port) : ts(std::make_unique<TcpServer>(port)) {
    }
    void HandlerHttpRequset(std::shared_ptr<Socket>& sock, InetAddr& client) {
        // std::string httpreqstr;
        // int n = sock->Recv(&httpreqstr);
        // if(n > 0) {
        //     HttpRequest req;
        //     req.Deserialisze(httpreqstr);
        //     // HttpResponse resp;
        //     // resp.SetTargetFile(req.uri());
        //     // resp.MakeResponse();
        //     HttpResponse resp;
        //     resp._version = "HTTP/1.1";
        //     resp._code = 200; // success
        //     resp._desc = "OK";
        //     //./wwwroot/a/b/c.html
        //     std::string filename = "./wwwroot/index.html";
        //     LOG(LogLevel::DEBUG) << "用户请求: " << filename;
        //     bool res = Util::ReadFileContent(filename, &(resp._text)); // 浏览器请求的资源，一定会存在吗？出错呢？
        //     (void)res;
        //     std::string response_str = resp.Serialize();
        //     sock->Send(response_str);
        // }
        // #ifndef DEBUG
        // #define DEBUG
        //         std::string httpstr;
        //         sock->Recv(&httpstr);
        //         std::cout << httpstr;
        // #endif
        // #ifndef DEBUG
// #define DEBUG
// #ifdef DEBUG
        // 收到请求
        std::string httpreqstr;
        // 假设：概率大，读到了完整的请求
        sock->Recv(&httpreqstr); // 浏览器给我发过来的是一个大的http字符串, 其实我们的recv也是有问题的。tcp是面向字节流的.
        std::cout << httpreqstr;

        // 直接构建http应答. 内存级别+固定
        HttpResponse resp;
        resp._version = "HTTP/1.1";
        resp._code = 200; // success
        resp._desc = "OK";

        std::string filename = webroot + "/" + homepage; // "./wwwroot/index.html";
        bool res = Util::ReadFileContent(filename, &(resp._text));
        (void)res;
        std::string response_str = resp.Serialize();
        sock->Send(response_str);
// #endif
    }
    void Start() {
        ts->Start([this](std::shared_ptr<Socket> &sock, InetAddr& client) {
            this->HandlerHttpRequset(sock, client);
        });
    }
    ~Http() {
        
    }
private:
    std::unique_ptr<TcpServer> ts;
};